1 module hip.hiprenderer.backend.gl.defaultshaders; 2 import hip.api.renderer.core; 3 import hip.config.renderer; 4 private enum GLDefaultShadersPath = __MODULE__; 5 6 7 static if(!HasOpenGL) 8 { 9 immutable DefaultShader[] DefaultShaders; 10 } 11 else: 12 13 immutable DefaultShader[] DefaultShaders = [ 14 HipShaderPresets.DEFAULT: DefaultShader(GLDefaultShadersPath, &getDefaultVertex, &getDefaultVertex), 15 HipShaderPresets.FRAME_BUFFER: DefaultShader(GLDefaultShadersPath, &getFrameBufferVertex, &getFrameBufferFragment), 16 HipShaderPresets.GEOMETRY_BATCH: DefaultShader(GLDefaultShadersPath, &getGeometryBatchVertex, &getGeometryBatchFragment), 17 HipShaderPresets.SPRITE_BATCH: DefaultShader(GLDefaultShadersPath, &getSpriteBatchVertex, &getSpriteBatchFragment), 18 HipShaderPresets.BITMAP_TEXT: DefaultShader(GLDefaultShadersPath, &getBitmapTextVertex, &getBitmapTextFragment), 19 HipShaderPresets.NONE: DefaultShader(GLDefaultShadersPath) 20 ]; 21 22 23 private { 24 25 version(GLES32) version = GLES3; 26 version(GLES30) version = GLES3; 27 28 version(GLES3) 29 { 30 enum shaderVersion = "#version 300 es"; 31 enum floatPrecision = "precision mediump float;"; 32 // enum floatPrecision = ""; 33 } 34 else version(GLES20) 35 { 36 enum shaderVersion = "#version 100"; 37 enum floatPrecision = "precision mediump float;"; 38 } 39 else 40 { 41 enum shaderVersion = "#version 330 core"; 42 enum floatPrecision = ""; 43 } 44 45 import hip.util.conv; 46 import hip.util.format: fastUnsafeCTFEFormat, format; 47 48 49 50 private string getBaseFragment() 51 { 52 __gshared string baseShader; 53 if(baseShader is null) 54 { 55 string defs; 56 version(WebAssembly) defs~= "#define WASM\n"; 57 version(PSVita) defs~= "#define PSVITA\n"; 58 baseShader = shaderVersion~"\n"~floatPrecision~"\n"~defs ~ 59 `#ifdef WASM 60 #define TEXTURE_2D texture2D 61 #elif defined(PSVITA) 62 #define TEXTURE_2D texture2D 63 #else 64 #define TEXTURE_2D texture 65 #endif`; 66 67 } 68 return baseShader; 69 } 70 71 72 73 string getDefaultFragment() 74 { 75 return getBaseFragment~q{ 76 77 uniform vec4 globalColor; 78 in vec4 vertexColor; 79 in vec2 tex_uv; 80 uniform sampler2D tex1; 81 out vec4 outPixelColor; 82 83 void main() 84 { 85 outPixelColor = vertexColor*globalColor*TEXTURE_2D(tex1, tex_uv); 86 } 87 }; 88 } 89 string getFrameBufferFragment() 90 { 91 return getBaseFragment~q{ 92 93 in vec2 inTexST; 94 uniform sampler2D uBufferTexture; 95 uniform vec4 uColor; 96 out vec4 outPixelColor; 97 98 void main() 99 { 100 vec4 col = TEXTURE_2D(uBufferTexture, inTexST); 101 float grey = (col.r+col.g+col.b)/3.0; 102 outPixelColor = grey * uColor; 103 } 104 }; 105 } 106 107 version(GLES20) //They are very different, so, better to keep them separate 108 { 109 string getSpriteBatchFragment() 110 { 111 import hip.hiprenderer.renderer; 112 int sup = HipRenderer.getMaxSupportedShaderTextures(); 113 string textureSlotSwitchCase; 114 if(sup == 1) textureSlotSwitchCase = "gl_FragColor = TEXTURE_2D(uTex[0], inTexST)*inVertexColor*uBatchColor;\n"; 115 else 116 { 117 for(int i = 0; i < sup; i++) 118 { 119 string strI = to!string(i); 120 if(i != 0) 121 textureSlotSwitchCase~="\t\t\t\telse "; 122 textureSlotSwitchCase~="if(texId == "~strI~")"~ 123 "{gl_FragColor = TEXTURE_2D(uTex["~strI~"], inTexST)*inVertexColor*uBatchColor;}\n"; 124 } 125 } 126 textureSlotSwitchCase~="}\n"; 127 enum shaderSource = q{ 128 uniform vec4 uBatchColor; 129 130 varying vec4 inVertexColor; 131 varying vec2 inTexST; 132 varying float inTexID; 133 134 void main() 135 }; 136 137 138 return getBaseFragment~format!q{ 139 uniform sampler2D uTex[%s];}(sup)~ 140 shaderSource~ 141 "{"~q{ 142 int texId = int(inTexID); 143 }~ textureSlotSwitchCase; 144 } 145 } 146 else 147 { 148 string getSpriteBatchFragment() 149 { 150 import hip.hiprenderer.renderer; 151 int sup = HipRenderer.getMaxSupportedShaderTextures(); 152 //Push the line breaks for easier debugging on gpu debugger 153 string textureSlotSwitchCase = "switch(texId)\n{\n"; 154 for(int i = 0; i < sup; i++) 155 { 156 string strI = to!string(i); 157 textureSlotSwitchCase~="case "~strI~": "~ 158 "\t\toutPixelColor = TEXTURE_2D(uTex["~strI~"], inTexST)*inVertexColor*uBatchColor;break;\n"; 159 } 160 textureSlotSwitchCase~="}\n"; 161 162 enum shaderSource = q{ 163 164 uniform vec4 uBatchColor; 165 166 in vec4 inVertexColor; 167 in vec2 inTexST; 168 in float inTexID; 169 170 out vec4 outPixelColor; 171 void main() 172 }; 173 return getBaseFragment~format!q{ 174 uniform sampler2D uTex[%s];}(sup)~ 175 shaderSource~ 176 "{"~q{ 177 int texId = int(inTexID); 178 } ~textureSlotSwitchCase~ 179 "}"; 180 // outPixelColor = texture(uTex[texId], inTexST)* inVertexColor * uBatchColor; 181 // outPixelColor = vec4(texId, texId, texId, 1.0)* inVertexColor * uBatchColor; 182 } 183 184 } 185 string getGeometryBatchFragment() 186 { 187 version(GLES20) 188 { 189 enum attr1 = q{varying}; 190 enum outputPixelVar = q{}; 191 enum outputAssignment = q{gl_FragColor}; 192 } 193 else 194 { 195 enum attr1 = q{in}; 196 enum outputPixelVar = q{out vec4 outPixelColor;}; 197 enum outputAssignment = q{outPixelColor}; 198 } 199 enum shaderSource = q{ 200 uniform vec4 uGlobalColor; 201 %s vec4 inVertexColor; 202 %s 203 204 void main() 205 { 206 %s = inVertexColor * uGlobalColor; 207 } 208 }.fastUnsafeCTFEFormat(attr1, outputPixelVar, outputAssignment); 209 return getBaseFragment~shaderSource; 210 } 211 212 string getBitmapTextFragment() 213 { 214 version(GLES20) 215 { 216 enum attr1 = q{varying}; 217 enum outputPixelVar = q{}; 218 enum outputAssignment = q{gl_FragColor}; 219 } 220 else 221 { 222 enum attr1 = q{in}; 223 enum outputPixelVar = q{out vec4 outPixelColor;}; 224 enum outputAssignment = q{outPixelColor}; 225 } 226 enum shaderSource = q{ 227 228 229 uniform vec4 uColor; 230 uniform sampler2D uTex; 231 %s vec2 inTexST; 232 %s 233 234 void main() 235 { 236 float r = TEXTURE_2D(uTex, inTexST).r; 237 %s = vec4(r,r,r,r)*uColor; 238 } 239 }.fastUnsafeCTFEFormat(attr1, outputPixelVar, outputAssignment); 240 return getBaseFragment~shaderSource; 241 } 242 243 244 // //getSDFFragment 245 // string getBitmapTextFragment() 246 // { 247 // version(GLES20) 248 // { 249 // enum attr1 = q{varying}; 250 // enum outputPixelVar = q{}; 251 // enum outputAssignment = q{gl_FragColor}; 252 // } 253 // else 254 // { 255 // enum attr1 = q{in}; 256 // enum outputPixelVar = q{out vec4 outPixelColor;}; 257 // enum outputAssignment = q{outPixelColor}; 258 // } 259 260 // enum shaderSource = q{ 261 // %s vec2 inTexST; 262 // %s 263 264 // uniform sampler2D uTex; 265 // // uniform vec4 bgColor; 266 // uniform vec4 uColor; 267 268 // float screenPxRange = 4.5; 269 270 // void main() { 271 // float sd = texture(uTex, inTexST).r; 272 // float screenPxDistance = screenPxRange*(sd - 0.5); 273 // float opacity = clamp(screenPxDistance + 0.5, 0.0, 1.0); 274 // // color = mix(bgColor, fgColor, opacity); 275 // %s = uColor * opacity; 276 // }}.fastUnsafeCTFEFormat(attr1, outputPixelVar, outputAssignment); 277 278 // return getBaseFragment~shaderSource; 279 // } 280 281 282 string getDefaultVertex() 283 { 284 return shaderVersion~"\n"~floatPrecision~"\n"~q{ 285 286 layout (location = 0) in vec3 position; 287 layout (location = 1) in vec4 color; 288 layout (location = 2) in vec2 texCoord; 289 uniform mat4 proj; 290 291 292 out vec4 vertexColor; 293 out vec2 tex_uv; 294 295 void main() 296 { 297 gl_Position = proj*vec4(position, 1.0); 298 vertexColor = color; 299 tex_uv = texCoord; 300 } 301 }; 302 } 303 string getFrameBufferVertex() 304 { 305 return shaderVersion~"\n"~floatPrecision~"\n"~q{ 306 307 layout (location = 0) in vec2 vPosition; 308 layout (location = 1) in vec2 vTexST; 309 310 out vec2 inTexST; 311 312 void main() 313 { 314 gl_Position = vec4(vPosition, 0.0, 1.0); 315 inTexST = vTexST; 316 } 317 }; 318 } 319 string getSpriteBatchVertex() 320 { 321 version(GLES20) //`in` representation in GLES 20 is `attribute`` 322 { 323 enum attr1 = q{attribute}; 324 enum attr2 = q{attribute}; 325 enum attr3 = q{attribute}; 326 enum attr4 = q{attribute}; 327 enum out1 = q{varying}; 328 enum out2 = q{varying}; 329 enum out3 = q{varying}; 330 } 331 else 332 { 333 enum attr1 = q{layout (location = 0) in}; 334 enum attr2 = q{layout (location = 1) in}; 335 enum attr3 = q{layout (location = 2) in}; 336 enum attr4 = q{layout (location = 3) in}; 337 enum out1 = q{out}; 338 enum out2 = q{out}; 339 enum out3 = q{out}; 340 } 341 enum shaderSource = q{ 342 %s vec3 vPosition; 343 %s vec4 vColor; 344 %s vec2 vTexST; 345 %s float vTexID; 346 347 uniform mat4 uMVP; 348 349 %s vec4 inVertexColor; 350 %s vec2 inTexST; 351 %s float inTexID; 352 353 void main() 354 { 355 gl_Position = uMVP*vec4(vPosition, 1.0); 356 inVertexColor = vColor; 357 inTexST = vTexST; 358 inTexID = vTexID; 359 } 360 }.fastUnsafeCTFEFormat(attr1, attr2, attr3, attr4, out1, out2, out3); 361 return shaderVersion~"\n"~floatPrecision~"\n"~shaderSource; 362 } 363 string getGeometryBatchVertex() 364 { 365 version(GLES20) 366 { 367 enum attr1 = q{attribute}; 368 enum attr2 = q{attribute}; 369 enum out1 = q{varying}; 370 } 371 else 372 { 373 enum attr1 = q{layout (location = 0) in}; 374 enum attr2 = q{layout (location = 1) in}; 375 enum out1 = q{out}; 376 } 377 378 enum shaderSource = q{ 379 380 %s vec3 vPosition; 381 %s vec4 vColor; 382 383 uniform mat4 uMVP; 384 385 %s vec4 inVertexColor; 386 387 void main() 388 { 389 gl_Position = uMVP*vec4(vPosition, 1.0); 390 inVertexColor = vColor; 391 } 392 }.fastUnsafeCTFEFormat(attr1, attr2, out1); 393 return shaderVersion~"\n"~floatPrecision~"\n"~shaderSource; 394 } 395 396 string getBitmapTextVertex() 397 { 398 version(GLES20) 399 { 400 enum attr1 = q{attribute}; 401 enum attr2 = q{attribute}; 402 enum out1 = q{varying}; 403 } 404 else 405 { 406 enum attr1 = q{layout (location = 0) in}; 407 enum attr2 = q{layout (location = 1) in}; 408 enum out1 = q{out}; 409 } 410 enum shaderSource = q{ 411 412 %s vec3 vPosition; 413 %s vec2 vTexST; 414 415 uniform mat4 uMVP; 416 417 %s vec2 inTexST; 418 419 void main() 420 { 421 gl_Position = uMVP * vec4(vPosition, 1.0); 422 inTexST = vTexST; 423 } 424 }.fastUnsafeCTFEFormat(attr1, attr2, out1); 425 return shaderVersion~"\n"~floatPrecision~"\n"~shaderSource; 426 } 427 428 }